using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Web.UI;
using System.Xml.Xsl;
using System.Diagnostics;
using Microsoft.SharePoint;
using System.Web;
using Microsoft.SharePoint.WebControls;
using IWCommunity.Common;

namespace IWCommunity.Blogs.WebControls
{
    public class XslTransformation : SPControl
    {
        private XmlDocument _document;
        private string _xslName = "";
        private int _itemsToDisplay = 10;
        private int _cacheTimeout = 2;
        private bool _cacheDebug = false;
        private bool _cacheHtml = false;
        private XsltArgumentList _xslArguments;
        private string _cacheKey;
        private bool _tranformErrorXml = false;
        private string _cacheID = "";
        private bool _cachePerPage = true;

        public bool TranformErrorXml
        {
            get { return _tranformErrorXml; }
            set { _tranformErrorXml = value; }
        }

        public bool CacheHtml
        {
            get { return _cacheHtml; }
            set { _cacheHtml = value; }
        }

        public int ItemsToDisplay
        {
            get { return _itemsToDisplay; }
            set { _itemsToDisplay = value; }
        }

        public int CacheTimeout
        {
            get { return _cacheTimeout; }
            set { _cacheTimeout = value; }
        }

        public virtual string CacheKey
        {
            get { return CacheKeyPrefix + _cacheKey; }
            set { _cacheKey = value; }
        }

        public string CacheID
        {
            get { return _cacheID; }
            set { _cacheID = value; }
        }

        public bool CachePerPage
        {
            get { return _cachePerPage; }
            set { _cachePerPage = value; }
        }


         public bool CacheDebug
        {
            get { return _cacheDebug; }
            set { _cacheDebug = value; }
        }

        protected virtual string CacheKeyPrefix
        {
            get
            {
                string sKey = "IW_" + HttpContext.Current.User.Identity.IsAuthenticated.ToString();

                //if (!BlogContext.Current.Settings.DisableConvertClientDates)
                //    sKey += "~" + BlogContext.Current.ClientTimeZoneOffsetFromWeb.ToString() + "~";

                if (CachePerPage)
                    sKey += HttpContext.Current.Request.Url.ToString();

                return sKey + _cacheID; //sKey + BlogContext.Current.BlogTheme + _cacheID;
            }
        }

        private bool _cachingEnabled = true;
        protected bool CachingEnabled
        {
            get
            {
               return _cachingEnabled;//BlogContext.Current.Settings.CachingEnabled;
            }
           
        }

        protected virtual string HtmlCacheKeySuffix
        {
            get
            {
                return "_Html_"; //+ BlogContext.Current.BlogTheme;
            }
        }

        public string XslName
        {
            get { return _xslName; }
            set { _xslName = value; }
        }

        public virtual XmlDocument Document
        {
            get
            {
                return _document;
            }
            set { _document = value; }
        }



        protected virtual string CachedHtml
        {
            get
            {
                if (!CachingEnabled || !CacheHtml) return null;

                return (string)HttpContext.Current.Cache[CacheKey + HtmlCacheKeySuffix];
            }
            set
            {
                if (!IsHtmlCached && CachingEnabled && CacheHtml)
                    HttpContext.Current.Cache.Add(CacheKey + HtmlCacheKeySuffix, value, null, DateTime.Now.AddMinutes(CacheTimeout), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal,null);
            }
        }

        
        public virtual bool IsHtmlCached
        {
            get
            {
                return HttpContext.Current.Cache[CacheKey + HtmlCacheKeySuffix] != null;
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            try//isCached
            {
                if (CacheHtml && CachingEnabled && IsHtmlCached)
                {
                    writer.Write(CachedHtml);
                    return;
                }

                XmlDocument oData = Document;
                
                if (oData == null) { oData = new XmlDocument(); oData.LoadXml("<Error>Document is null</Error>"); }

                if (oData.DocumentElement.Name == "Error" && !TranformErrorXml)
                {
                    writer.Write(string.Format("<div style='color:red'>Failed to render control: {0}</div>", oData.DocumentElement.InnerText));
                    return;
                }

                //TODO:check dates thing
                //if (!BlogContext.Current.Settings.DisableConvertClientDates)
                    //oData = ConvertDates(oData);

                XslCompiledTransform oTransform = LoadStylesheet();
                if (oTransform == null) return;

                HtmlTextWriter tw = writer;

                if (!IsHtmlCached && CachingEnabled && CacheHtml)
                    tw = new HtmlTextWriter(new System.IO.StringWriter()); 
                
                             
                oTransform.Transform(oData, XslArguments, tw);

                string cacheDebug = string.Empty;
                if (CacheDebug)
                    cacheDebug = string.Format("<div style='color:red'>Rendered at {0}</div>",DateTime.Now);

                if (!IsHtmlCached && CachingEnabled && CacheHtml)
                {
                    CachedHtml = tw.InnerWriter.ToString() + cacheDebug;
                    writer.Write(CachedHtml);
                }
                else if (CacheDebug)
                    writer.Write(cacheDebug);
                
               
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                writer.Write(string.Format("<div style='color:red'>Failed to render control: {0}</div>", ex.Message));
            }
        }

        //private XmlDocument ConvertDates(XmlDocument oData)
        //{
        //    if (oData.DocumentElement.GetAttribute("datesConverted") == "true") return oData;

        //    Debug.WriteLine("Converting client dates: Offset=" + BlogContext.Current.ClientTimeZoneOffsetFromWeb.ToString());

        //    XmlDocument oNew = new XmlDocument();
        //    oNew.LoadXml(oData.OuterXml);

        //    XmlNodeList oList = oNew.DocumentElement.SelectNodes("//Created | //PublishedDate | //Modified");
        //    foreach (XmlElement oDate in oList)
        //        oDate.InnerText = XslMethods.clientDateTime(oDate.InnerText);

        //    oNew.DocumentElement.SetAttribute("datesConverted", "true");

        //    return oNew;
        //}

        private XslCompiledTransform LoadStylesheet()
        {
            SPWeb oCurrentWeb = SPContext.Current.Web;

            object oCachedXsl = HttpContext.Current.Cache["IW_Xsl_" + oCurrentWeb.Url + "__" + XslName]; //+ BlogContext.Current.BlogTheme + "__" + XslName];
            if (oCachedXsl != null && !oCurrentWeb.UserIsWebAdmin) return (XslCompiledTransform)oCachedXsl;

            try
            {
                XmlDocument oXsl = new XmlDocument(); //get style sheets from root web's blogstyles folder
                oXsl.LoadXml(oCurrentWeb.GetFileAsString(oCurrentWeb.Site.RootWeb.Url + "/BlogStyles/" + XslName)); //oCurrentWeb.Url + "/BlogStyles/" + BlogContext.Current.BlogTheme + "/" + XslName));

                XslCompiledTransform oTransform = new XslCompiledTransform();
                oTransform.Load(oXsl);

                if (!oCurrentWeb.UserIsWebAdmin)
                    HttpContext.Current.Cache.Add("IW_Xsl_" + oCurrentWeb.Url + "__" + XslName, oTransform, null, DateTime.Now.AddMinutes(20), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);

                return oTransform;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                return null;
            }
        }

        public virtual XsltArgumentList XslArguments
        {
            get
            {
                if (_xslArguments != null) return _xslArguments;

                _xslArguments = new XsltArgumentList();

                _xslArguments.AddParam("IsBlogOwner", "", BlogContext.Current.IsBlogOwner);
                _xslArguments.AddParam("ItemsToDisplay", "", ItemsToDisplay.ToString());
                _xslArguments.AddParam("Now", "", DateTime.Now.ToString());
                _xslArguments.AddParam("WebUrl", "", SPContext.Current.Web.Url);
                _xslArguments.AddParam("SiteUrl", "", SPContext.Current.Site.Url);

                _xslArguments.AddParam("SecureSystemPages", "", true);//BlogContext.Current.Settings.SecureSystemPages);
                _xslArguments.AddParam("ThemeSelectorEnabled", "", false); //BlogContext.Current.Settings.ThemeSelectorEnabled);
                _xslArguments.AddParam("TrimPostBodyOnLists", "", true); //BlogContext.Current.Settings.TrimPostBodyOnLists);

               // _xslArguments.AddParam("BlogTransformParameter1", "", (BlogContext.Current.Settings.BlogTransformParameter1 == null) ? "" : BlogContext.Current.Settings.BlogTransformParameter1);
               // _xslArguments.AddParam("BlogTransformParameter2", "", (BlogContext.Current.Settings.BlogTransformParameter1 == null) ? "" : BlogContext.Current.Settings.BlogTransformParameter2);
               // _xslArguments.AddParam("BlogTransformParameter3", "", (BlogContext.Current.Settings.BlogTransformParameter1 == null) ? "" : BlogContext.Current.Settings.BlogTransformParameter3);

                //_xslArguments.AddParam("CustomRssUrl", "", ""); //(BlogContext.Current.Settings.CustomRSSFeedUrl == null) ? "" : BlogContext.Current.Settings.CustomRSSFeedUrl);
                _xslArguments.AddParam("CurrentUrl", "", HttpContext.Current.Request.Url.ToString());

                string sRelativeUrl = SPContext.Current.Web.ServerRelativeUrl;
                if (sRelativeUrl.EndsWith("/")) sRelativeUrl = sRelativeUrl.Substring(0, sRelativeUrl.Length - 1);
                _xslArguments.AddParam("RelativeUrl", "", sRelativeUrl);

                // Add the query parameters
                foreach (string sKey in HttpContext.Current.Request.QueryString.AllKeys)
                    _xslArguments.AddParam("QS" + sKey.ToLower(), "", (HttpContext.Current.Request[sKey] == null) ? "" : HttpContext.Current.Request[sKey]);

                if (!string.IsNullOrEmpty(HttpContext.Current.Request["id"]))
                {
                    try
                    {
                        SPList oPosts = SPContext.Current.Web.Lists["Posts"];
                        SPListItem oPost = oPosts.GetItemById(int.Parse(HttpContext.Current.Request["id"]));

                        if (oPost != null)
                        {
                            _xslArguments.AddParam("PostTitle", "", oPost.Title);
                            _xslArguments.AddParam("PostUniqueId", "", oPost.UniqueId);
                           // string sLink = XslMethods.createPostUrl(((DateTime)oPost["Created"]).ToString("yyyy-MM-dd HH:mm"), (string)oPost["BlogTitleForUrl"]);
                            _xslArguments.AddParam("PostFullUrl", "", oPost.Url); //SPContext.Current.Site.Url + sLink);
                        }
                    }
                    catch { }
                }

                _xslArguments.AddExtensionObject("http://exslt.org/dates-and-times", new Mvp.Xml.Exslt.ExsltDatesAndTimes());
                _xslArguments.AddExtensionObject("http://exslt.org/strings", new Mvp.Xml.Exslt.ExsltStrings());
                _xslArguments.AddExtensionObject("http://exslt.org/sets", new Mvp.Xml.Exslt.ExsltSets());
                _xslArguments.AddExtensionObject("http://exslt.org/math", new Mvp.Xml.Exslt.ExsltMath());
               // _xslArguments.AddExtensionObject("http://cks/ebemethods", new XslMethods());

                return _xslArguments;
            }
            
        }
    }

}
